package tools

import (
	"crypto/tls"
	"encoding/json"
	"fmt"
	"github.com/astaxie/beego/logs"
	"io/ioutil"
	"lazyops_go/models"
	"net/http"
	"net/url"
	"strconv"
	"strings"
)

var (
	salt_url,_ = models.QueryDictKey("SALT_URL")
	salt_user,_ = models.QueryDictKey("SALT_USER")
	salt_passwd,_ = models.QueryDictKey("SALT_PASS")
)

func PostReq(obj url.Values,prefix,token_id string) string {
	apiUrl := salt_url.DictVal + prefix
	u, _ := url.ParseRequestURI(apiUrl)
	urlStr := u.String()

	tr := &http.Transport{
		TLSClientConfig:    &tls.Config{InsecureSkipVerify: true},
	}
	client := &http.Client{Transport: tr}

	//client := &http.Client{}
	req, _ := http.NewRequest("POST", urlStr, strings.NewReader(obj.Encode()))
	req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
	if prefix == "/login"{
		fmt.Println(token_id)
	}else{
		req.Header.Set("X-Auth-Token",token_id)
	}

	req.Header.Add("Content-Length", strconv.Itoa(len(obj.Encode())))

	resp, err := client.Do(req)
	if err != nil {
		logs.Error(err.Error())
		return "err"
	}
	defer resp.Body.Close()
	respBytes, err := ioutil.ReadAll(resp.Body)
	return string(respBytes)
}

func GetToken() string {
	var taken_id  string
	postData := url.Values{}
	postData.Set("eauth", "pam")
	postData.Set("username", salt_user.DictVal)
	postData.Set("password", salt_passwd.DictVal)
	data := PostReq(postData,"/login","")
	js := []byte(data)
	m := map[string]interface{}{}
	if err := json.Unmarshal(js, &m); err != nil {
		panic(err)
	}
	for _,v:= range m["return"].([]interface{}){
		for k, v1 := range v.(map[string]interface{}){
			if k == "token" {
				taken_id = v1.(string)
			}

		}
	}
	return taken_id
}

func SaltRunArg(tgt,model,arg,run_user string) string {
	runas := "runas="+run_user
	postData := url.Values{}
	postData.Set("client", "local")
	postData.Set("tgt", tgt)
	postData.Set("fun", model)
	postData.Set("arg", arg)
	postData.Set("tgt_type", "list")
	postData.Add("arg", runas)
	tokenId := GetToken()
	data := PostReq(postData,"/",tokenId)
	return data
}

func SaltRunArgs(tgt,model,arg,args,run_user string) string {
	//salt api 多参数接口
	arg_str := strings.Replace(args, ",", " ", -1)
	runas := "runas="+run_user
	postData := url.Values{}
	postData.Set("client", "local")
	postData.Set("tgt", tgt)
	postData.Set("fun", model)
	postData.Set("arg", arg)
	postData.Add("arg", arg_str)
	postData.Set("tgt_type", "list")
	postData.Add("arg", runas)
	tokenId := GetToken()
	data := PostReq(postData,"/",tokenId)
	return data
}



func SaltUploadFile(tgt,model,arg_src,arg_dest,run_user string) string {
	runas := "runas="+run_user
	postData := url.Values{}
	postData.Set("client", "local")
	postData.Set("tgt", tgt)
	postData.Set("fun", model)
	postData.Set("arg", arg_src)
	postData.Add("arg", arg_dest)
	postData.Add("arg", "makedirs=True")
	postData.Set("tgt_type", "list")
	postData.Add("arg", runas)
	tokenId := GetToken()
	data := PostReq(postData,"/",tokenId)
	return data
}


func SaltRun(tgt,model string) string {
	postData := url.Values{}
	postData.Set("client", "local")
	postData.Set("tgt", tgt)
	postData.Set("fun", model)
	postData.Set("expr_form", "list")
	tokenId := GetToken()
	data := PostReq(postData,"/",tokenId)
	return data
}



func TestSalt(ip string) bool {
	ret := SaltRunArg(ip,"cmd.run","echo PONG","root")
	logs.Info(ret)
	js :=[]byte(ret)
	m := map[string]interface{}{}
	json.Unmarshal(js,&m)
	for _,v := range m["return"].([]interface{}){
		for k, v1 := range v.(map[string]interface{}){
			if k == ip {
				defer func() {
					err := recover()
					logs.Error("err:",err)
				}()
				status := v1.(string)
				if status == "PONG"{
					return true
				}
			}

		}
	}
	return false
}


func SaltRunArgRet(tgt,model,arg,run_user string) string {
	runas := "runas="+run_user
	postData := url.Values{}
	postData.Set("client", "local")
	postData.Set("tgt", tgt)
	postData.Set("fun", model)
	postData.Set("arg", arg)
	postData.Set("expr_form", "list")
	postData.Add("arg", runas)
	tokenId := GetToken()
	data := PostReq(postData,"/",tokenId)
	js := []byte(data)
	m := map[string]interface{}{}
	if err := json.Unmarshal(js, &m); err != nil {
		panic(err)
	}
	for _,v:= range m["return"].([]interface{}){
		for k, v1 := range v.(map[string]interface{}){
			if k == tgt {
				defer func() {
					err := recover()
					logs.Error("err:",err)
				}()
				return v1.(string)
			}
		}
	}
	return data
}